//
//  LWPopupViewController_Swift.swift
//  LWPopupViewController-Swift
//
//  Created by 钟志远 on 2021/1/6.
//

import Foundation
import UIKit
import SnapKit

nonisolated(unsafe) var popupViewControllerKey = 0
open class LWPopupViewController: UIViewController {
    
    public var bgColor: UIColor = UIColor.black.withAlphaComponent(0.3) {
        didSet {
            view.backgroundColor = bgColor
        }
    }

    public var dismissBlock: (() -> Void)?
    public var shouldDisableBgTap = false
    public lazy var animationContainer = LWPopupAnimationContainer()
    private weak var parentRetainer: NSObject?
    
    public var contentView: UIView?
    
    open override func loadView() {
        view = LWPopupView()
    }
    
    open var customView: LWPopupView {
        return view as! LWPopupView
    }
    
    
    public init() {
        super.init(nibName: nil, bundle: nil)
        self.modalTransitionStyle = .crossDissolve
        self.modalPresentationStyle = .overCurrentContext
    }
    
    required public init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
//    open override func viewWillAppear(_ animated: Bool) {
//        super.viewWillAppear(animated)
//        self.endAppearanceTransition()
//    }
    
    open override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        addTarget()
    }

    func setupUI() {
        customView.willMoveToSuperViewBlock = {[unowned self] parentView in
            if parentView == nil {
                return
            }

            self.view.alpha = 0
            self.animationContainer.showAnimation?(self, {[unowned self] _ in
                if self.presentingViewController == nil {
                    self.endAppearanceTransition()
                }
            })
        }
        
        view.backgroundColor = bgColor
    }
    
    func addTarget() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(bgViewTag))
        view.addGestureRecognizer(tap)
    }
    
    @objc func bgViewTag() {
        if self.shouldDisableBgTap {
            return;
        }
        
        hidden()
        
    }
    
    //MARK: addContent
    
    public func addContent(view: UIView) {
        self.view.addSubview(view)
        contentView = view
        view.snp.makeConstraints { make in
            make.center.equalToSuperview()
        }
        let tap = UITapGestureRecognizer(target: self, action: #selector(contentViewTap))
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }
    
    @objc func contentViewTap() { }
    

   public func addContent(viewController: UIViewController) {
        addContent(view: viewController.view)
        addChild(viewController)
        viewController.didMove(toParent: self)
    }
    
    public func convenRetain(obj: NSObject) {
        var container = objc_getAssociatedObject(obj, &popupViewControllerKey) as? [Any]
        if container == nil {
           container = []
            objc_setAssociatedObject(obj, &popupViewControllerKey, container, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        container?.append(self);
        objc_setAssociatedObject(obj, &popupViewControllerKey, container, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        parentRetainer = obj
    }
    
    //MARK: show
    public func show(inView view: UIView) {
        beginAppearanceTransition(true, animated: true)
        view.addSubview(self.view)
        if animationContainer is LWPopupAnimationSheetStyle {
            contentView?.snp.remakeConstraints({ (ConstraintMaker) in
                ConstraintMaker.left.bottom.right.equalToSuperview()
            })
        }
        
        self.view.snp.makeConstraints { (ConstraintMaker) in
            ConstraintMaker.edges.equalToSuperview()
        }
    }
    
    public func show(inViewController viewController: UIViewController) {
        show(inView: viewController.view)
        viewController.addChild(self)
        didMove(toParent: viewController)

    }
    
    //MARK: hidden
    public func hidden(completeBlock:  ( () -> Void)? = nil) {
        self.dismissBlock = completeBlock
        if parent != nil {
            beginAppearanceTransition(false, animated: true)
            self.animationContainer.hiddenAnimation?(self, {[unowned self] b in
                willMove(toParent: nil)
                
                ///-----
                ///endAppearanceTransition 正确的使用位置
                self.view.removeFromSuperview()
                endAppearanceTransition()
                self.cleanContent()
                //------
                
                self.removeFromParent()
                completeBlock?()
//                self.dismissBlock?()

            })
            
        } else if presentingViewController != nil {
            beginAppearanceTransition(false, animated: true)
            dismiss(animated: true) {[unowned self] in
                endAppearanceTransition()
                self.dismissBlock?()
                self.cleanContent()
            }
        } else {
            beginAppearanceTransition(false, animated: true)
            self.animationContainer.hiddenAnimation?(self, {[unowned self] b in
                self.view.removeFromSuperview()
                endAppearanceTransition()
                self.cleanContent()
            })
        }
    }
    
    //MARK: other
    
    open override func viewDidDisappear(_ animated: Bool) {
        clearContainer()
    }
    
    func cleanContent() {
        _ = children.map{$0.view.removeFromSuperview()}
        _ = children.map{$0.willMove(toParent: nil)}
        _ = children.map{$0.removeFromParent()}
    }
    
    func clearContainer() {
        if self.parentRetainer == nil {
           return
        }
        
        let container = objc_getAssociatedObject(self.parentRetainer!, &popupViewControllerKey) as? [Any]
        
        guard var c = container else {
            print("something wrong, container should not be nil!!!")
            return
        }
        
        if let index = c.firstIndex(where: {$0 as! NSObject  == self}) {
            c.remove(at: index)
        }
        
        if c.count == 0 {
            objc_setAssociatedObject(self.parentRetainer!, &popupViewControllerKey, nil, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }

    }
    
    deinit {
        print("deinit\(self)")
    }
}
